package httplog

import (
	"container/list"
	"encoding/json"
	"fmt"
	"net/http"
	"strconv"
	"strings"
	"sync"
	"unicode"

	"gitee.com/haodreams/libs/easy"
	"gitee.com/haodreams/golib/logs"
)

var l = WebWriter{
	MaxLines: 300,
	msgList:  list.New(),
}

func init() {
	logs.AddWriter(&l)
}

//WebWriter web 日志类
type WebWriter struct {
	sync.RWMutex     // write log order by order and  atomic incr maxLinesCurLines and maxSizeCurSize
	MaxLines     int `json:"maxlines"`
	msgList      *list.List
}

//Init 初始化
func (m *WebWriter) Init(config string) (err error) {
	if config == "" {
		return
	}
	err = json.Unmarshal([]byte(config), m)
	if err != nil {
		return err
	}
	return
}

//Write .
func (m *WebWriter) Write(b []byte) (n int, err error) {
	//log.Println(string(b))
	m.Lock()
	defer m.Unlock()

	//log.Println("lock")
	if m.msgList.Len() >= m.MaxLines {
		elem := m.msgList.Back()
		m.msgList.Remove(elem)
	}
	m.msgList.PushFront(string(b))
	n = len(b)
	return
}

// {"Name": "time","Title":"时间","Type":"string","Width":160},
// {"Name": "level","Title":"级别","Type":"string","Width":70},
// {"Name": "caller","Title":"位置","Type":"string","Width":170},
// {"Name": "message","Title":"消息","Type":"string"}
type Row struct {
	Time   string `json:"time"`
	Level  string `json:"level"`
	Caller string `json:"caller"`
	Msg    string `json:"message"`
}

//HTTPLogs http 请求日志
func HTTPLogs(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	pos := 0
	limit := 100
	s := r.FormValue("limit")
	if s != "" {
		li, err := strconv.Atoi(s)
		if err == nil {
			limit = li
		}
	}

	s = r.FormValue("page")
	if s != "" {
		st, err := strconv.Atoi(s)
		if err == nil {
			pos = (st - 1) * limit
		}
	}

	line := 0
	idx := 0
	rows := make([]string, limit)
	end := pos + limit

	l.RLock()
	count := l.msgList.Len()
	if end > count {
		end = count
	}
	for e := l.msgList.Front(); e != nil; e = e.Next() {
		idx++
		if idx > pos && line < end {
			rows[line], _ = e.Value.(string)
			line++
		}
		if idx >= end {
			break
		}
	}
	l.RUnlock()
	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	w.Write([]byte(fmt.Sprintf(`{"count":%d,"code":%d, "msg":"", "data":[`, count, 200)))

	first := true
	for j := 0; j < line; j++ {
		if rows[j][0] == '{' {
			if j > 0 {
				w.Write([]byte(","))
			}
			w.Write([]byte(rows[j]))
		} else {
			if len(rows[j]) == 0 {
				continue
			}

			if rows[j][0] == '{' {
				if first {
					first = false
				} else {
					w.Write([]byte(","))
				}
				w.Write([]byte(rows[j]))
			} else {
				ss := easy.FieldsFuncN(rows[j], unicode.IsSpace, 5)
				if len(ss) != 5 {
					continue
				}
				if first {
					first = false
				} else {
					w.Write([]byte(","))
				}
				row := new(Row)
				row.Time = ss[0] + " " + ss[1]
				row.Level = strings.TrimSuffix(ss[2], "\x1b[0m")
				if len(row.Level) > 5 {
					row.Level = row.Level[5:]
				}
				row.Caller = ss[3]
				row.Msg = ss[4]
				bs, err := json.Marshal(row)
				if err != nil {
					continue
				}
				w.Write(bs)
			}

		}
	}
	w.Write([]byte("]}"))
}
